package com.fuxi.cloud.dyndb.query;

import com.fuxi.cloud.common.util.CommonUtils;
import com.fuxi.cloud.common.util.oConvertUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * QueryGenerator
 *
 * @Author: 扫地僧
 * @CreateTime: 2021-05-03
 */
public class QueryGenerator {
    private static final Logger log = LoggerFactory.getLogger(QueryGenerator.class);
    public static final String SQL_RULES_COLUMN = "SQL_RULES_COLUMN";
    private static final String BEGIN = "_begin";
    private static final String END = "_end";
    private static final String MULTI = "_MultiString";
    private static final String STAR = "*";
    private static final String COMMA = ",";
    private static final String NOT_EQUAL = "!";
    private static final String QUERY_SEPARATE_KEYWORD = " ";
    private static final String SUPER_QUERY_PARAMS = "superQueryParams";
    private static final String SUPER_QUERY_MATCH_TYPE = "superQueryMatchType";
    public static final String SQL_SQ = "'";
    private static final String ORDER_COLUMN = "column";
    private static final String ORDER_TYPE = "order";
    private static final String ORDER_TYPE_ASC = "ASC";
    public static final String LIKE_MYSQL_SPECIAL_STRS = "_,%";
    private static final ThreadLocal<SimpleDateFormat> local = new ThreadLocal();
    private static String DB_TYPE;

    public QueryGenerator() {
    }

    private static SimpleDateFormat getTime() {
        SimpleDateFormat var0 = (SimpleDateFormat)local.get();
        if (var0 == null) {
            var0 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            local.set(var0);
        }

        return var0;
    }

    private static QueryRuleEnum convert2Rule(Object value) {
        if (value == null) {
            return null;
        } else {
            String var1 = (value + "").toString().trim();
            if (var1.length() == 0) {
                return null;
            } else {
                QueryRuleEnum var2 = null;
                if (var2 == null && var1.length() >= 3 && " ".equals(var1.substring(2, 3))) {
                    var2 = QueryRuleEnum.getByValue(var1.substring(0, 2));
                }

                if (var2 == null && var1.length() >= 2 && " ".equals(var1.substring(1, 2))) {
                    var2 = QueryRuleEnum.getByValue(var1.substring(0, 1));
                }

                if (var2 == null && var1.contains("*")) {
                    if (var1.startsWith("*") && var1.endsWith("*")) {
                        var2 = QueryRuleEnum.LIKE;
                    } else if (var1.startsWith("*")) {
                        var2 = QueryRuleEnum.LEFT_LIKE;
                    } else if (var1.endsWith("*")) {
                        var2 = QueryRuleEnum.RIGHT_LIKE;
                    }
                }

                if (var2 == null && var1.contains(",")) {
                    var2 = QueryRuleEnum.IN;
                }

                if (var2 == null && var1.startsWith("!")) {
                    var2 = QueryRuleEnum.NE;
                }

                return var2 != null ? var2 : QueryRuleEnum.EQ;
            }
        }
    }

    private static Object replaceValue(QueryRuleEnum rule, Object value) {
        if (rule == null)
            return null;
        if (!(value instanceof String))
            return value;
        String str = (value + "").toString().trim();
        if (rule == QueryRuleEnum.LIKE) {
            value = str.substring(1, str.length() - 1);
            value = specialStrConvert(value.toString());
        } else if (rule == QueryRuleEnum.LEFT_LIKE || rule == QueryRuleEnum.NE) {
            value = str.substring(1);
            value = specialStrConvert(value.toString());
        } else if (rule == QueryRuleEnum.RIGHT_LIKE) {
            value = str.substring(0, str.length() - 1);
            value = specialStrConvert(value.toString());
        } else if (rule == QueryRuleEnum.IN) {
            value = str.split(",");
        } else if (str.startsWith(rule.getValue())) {
            value = str.replaceFirst(rule.getValue(), "");
        } else if (str.startsWith(rule.getCondition() + " ")) {
            value = str.replaceFirst(rule.getCondition() + " ", "").trim();
        }
        return value;
    }

    private static Date getDateQueryByRule(String value, QueryRuleEnum rule) throws ParseException {
        Date var2 = null;
        if (value.length() == 10) {
            if (rule == QueryRuleEnum.GE) {
                var2 = getTime().parse(value + " 00:00:00");
            } else if (rule == QueryRuleEnum.LE) {
                var2 = getTime().parse(value + " 23:59:59");
            }
        }

        if (var2 == null) {
            var2 = getTime().parse(value);
        }

        return var2;
    }

    private static boolean judgedIsUselessField(String name) {
        return "class".equals(name) || "ids".equals(name) || "page".equals(name) || "rows".equals(name) || "sort".equals(name) || "order".equals(name);
    }

    public static String trimSingleQuote(String ruleValue) {
        if (oConvertUtils.isEmpty(ruleValue)) {
            return "";
        } else {
            if (ruleValue.startsWith("'")) {
                ruleValue = ruleValue.substring(1);
            }

            if (ruleValue.endsWith("'")) {
                ruleValue = ruleValue.substring(0, ruleValue.length() - 1);
            }

            return ruleValue;
        }
    }

    public static Set<String> getSqlRuleParams(String sql) {
        if (oConvertUtils.isEmpty(sql)) {
            return null;
        } else {
            HashSet var1 = new HashSet();
            String var2 = "\\#\\{\\w+\\}";
            Pattern var3 = Pattern.compile(var2);
            Matcher var4 = var3.matcher(sql);

            while(var4.find()) {
                String var5 = var4.group();
                var1.add(var5.substring(var5.indexOf("{") + 1, var5.indexOf("}")));
            }

            return var1;
        }
    }

    public static String getSingleQueryConditionSql(String field, String alias, Object value, boolean isString) {
        if (value == null) {
            return "";
        } else {
            field = alias + oConvertUtils.camelToUnderline(field);
            QueryRuleEnum var4 = convert2Rule(value);
            return getSingleSqlByRule(var4, field, value, isString);
        }
    }

    public static String getSingleSqlByRule(QueryRuleEnum rule, String field, Object value, boolean isString) {
        String var4 = "";
        switch(rule) {
            case GT:
                var4 = field + rule.getValue() + getFieldConditionValue(value, isString);
                break;
            case GE:
                var4 = field + rule.getValue() + getFieldConditionValue(value, isString);
                break;
            case LT:
                var4 = field + rule.getValue() + getFieldConditionValue(value, isString);
                break;
            case LE:
                var4 = field + rule.getValue() + getFieldConditionValue(value, isString);
                break;
            case EQ:
                var4 = field + rule.getValue() + getFieldConditionValue(value, isString);
                break;
            case NE:
                var4 = field + " <> " + getFieldConditionValue(value, isString);
                break;
            case IN:
                var4 = field + " in " + getInConditionValue(value, isString);
                break;
            case LIKE:
                var4 = field + " like " + getLikeConditionValue(value);
                break;
            case LEFT_LIKE:
                var4 = field + " like " + getLikeConditionValue(value);
                break;
            case RIGHT_LIKE:
                var4 = field + " like " + getLikeConditionValue(value);
                break;
            default:
                var4 = field + " = " + getFieldConditionValue(value, isString);
        }

        return var4;
    }

    private static String getFieldConditionValue(Object value, boolean isString) {
        String var2 = value.toString().trim();
        if (var2.startsWith("!")) {
            var2 = var2.substring(1);
        } else if (var2.startsWith(">=")) {
            var2 = var2.substring(2);
        } else if (var2.startsWith("<=")) {
            var2 = var2.substring(2);
        } else if (var2.startsWith(">")) {
            var2 = var2.substring(1);
        } else if (var2.startsWith("<")) {
            var2 = var2.substring(1);
        }

        if (isString) {
            return "SQLSERVER".equals(getDbType()) ? " N'" + var2 + "' " : " '" + var2 + "' ";
        } else {
            return "SQLSERVER".equals(getDbType()) && var2.endsWith("'") && var2.startsWith("'") ? " N" + var2 : value.toString();
        }
    }

    private static String getInConditionValue(Object value, boolean isString) {
        if (isString) {
            String[] var2 = value.toString().split(",");
            String var3 = "";
            String[] var4 = var2;
            int var5 = var2.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String var7 = var4[var6];
                if ("SQLSERVER".equals(getDbType())) {
                    var3 = var3 + ",N'" + var7 + "'";
                } else {
                    var3 = var3 + ",'" + var7 + "'";
                }
            }

            return "(" + var3.substring(1) + ")";
        } else {
            return "(" + value.toString() + ")";
        }
    }

    private static String getLikeConditionValue(Object value) {
        String var1 = value.toString().trim();
        if (var1.startsWith("*") && var1.endsWith("*")) {
            return "SQLSERVER".equals(getDbType()) ? "N'%" + var1.substring(1, var1.length() - 1) + "%'" : "'%" + var1.substring(1, var1.length() - 1) + "%'";
        } else if (var1.startsWith("*")) {
            return "SQLSERVER".equals(getDbType()) ? "N'%" + var1.substring(1) + "'" : "'%" + var1.substring(1) + "'";
        } else if (var1.endsWith("*")) {
            return "SQLSERVER".equals(getDbType()) ? "N'" + var1.substring(0, var1.length() - 1) + "%'" : "'" + var1.substring(0, var1.length() - 1) + "%'";
        } else if (var1.indexOf("%") >= 0) {
            if ("SQLSERVER".equals(getDbType())) {
                return var1.startsWith("'") && var1.endsWith("'") ? "N" + var1 : "N'" + var1 + "'";
            } else {
                return var1.startsWith("'") && var1.endsWith("'") ? var1 : "'" + var1 + "'";
            }
        } else {
            return "SQLSERVER".equals(getDbType()) ? "N'%" + var1 + "%'" : "'%" + var1 + "%'";
        }
    }

    private static String getDbType() {
        return CommonUtils.getDatabaseType();
    }

    private static List<Field> getClassFields(Class<?> clazz) {
        ArrayList var1 = new ArrayList();

        do {
            Field[] var2 = clazz.getDeclaredFields();

            for(int var3 = 0; var3 < var2.length; ++var3) {
                var1.add(var2[var3]);
            }

            clazz = clazz.getSuperclass();
        } while(clazz != Object.class && clazz != null);

        return var1;
    }

    private static String specialStrConvert(String value) {
        if ("MYSQL".equals(getDbType())) {
            String[] var1 = "_,%".split(",");
            String[] var2 = var1;
            int var3 = var1.length;

            for(int var4 = 0; var4 < var3; ++var4) {
                String var5 = var2[var4];
                if (value.indexOf(var5) != -1) {
                    value = value.replace(var5, "\\" + var5);
                }
            }
        }

        return value;
    }
}

